;	mrs mod , submenus are signed with <> not with []

;------------------------------------------------------------------------------------------------
; Function:		ShowMenu
;				Show menu from the text.
;  
; Parameters: 
;				mDef	- Textual menu definition.
;				mnu		- Menu to show. Label with the same name as menu will be launched on item selection.
;						  "" means first menu will be shown (default)
;				sub		- Optional subroutine that will override default label (named by menu)
;				sep		- Optional separator char used for menu items in menu definition, by default new line
;				
; Returns:      
;				Message describing error if it ocured or new line separated list of created menus.
;				If return value is blank, ShowMenu just displayed menu already created in one of previous calls.
;
;	
; Remarks:
;				You must have in the code label with the same name as that given to the menu, otherwise
;				ShowMenu returns "No Label" error (unless you used "sub" parameter in which case the same 
;				applies to that subroutine). There must be no white space between menu name and start of the line.
;				Set each menu item on new line, use "-" to define separator.
;
; Metachars:
;				To create *submenu*, use "item = [submenu]" notation where submenu must exist in the textual 
;				menu definition. Referencing any particular menu as submenu multiple times will work 
;				correctly, but circular references must be avoided.
;				To make item *checked*, use "+" as first character of its name, to make it *disabled* use "*".
;				To associated *user data* use "=data" after the item. If text after = doesn't contain valid
;				submenu reference, it will be seen as user data. This also means that submenu items can contain data.
;				To make menu definition more compact use something else then new line as item separator
;				for instance "|" :
;>
;>					[Mnu1]
;>					item1|item2|item3|-|item4=[Mnu2]|item5
;>					[Mnu2]
;>					menu21 = menu21|menu22|menu23|menu24									  
;>				
;				You can then use this command to show the menu
;>					ShowMenu(mDef, "", "", "|")				;use first menu found and | as item separator
;
; About:
;				v1.2 by majkinetor
;				See:  http://www.autohotkey.com/forum/topic23138.html
;
ShowMenu( mDef, mnu="", sub="", sep="`n", r=0 ) {
	static p, menus
	if (!r)  {
		if (mnu = "") and (SubStr(mDef, 1, 1) = "[")				;use first menu if mnu = ""
			mnu := SubStr(mDef, 2, InStr(mDef, "]")- 2)
		p := sub="" ? mnu : sub, menus:=""							;set on function call (not on recursion step)
	}

	Menu, %mnu%, UseErrorLevel, on
	Menu, %mnu%, Color,											    ;check if menu already exists
	if !ErrorLevel
		if !r {														;if this is first call, show the menu
			Menu, %mnu%, Show
			return 
		} else return												; otherwise this is recursion step so just return
	
	if !(r || IsLabel(p))
		return "No Label"

	if !(s := SubStr(mDef, 1, StrLen(mnu)+2) = "[" mnu "]" )		;start index
		s := InStr(mDef, "`n[" mnu "]")
	IfEqual, s, 0, Return "Menu not found"
	
	if !(e := InStr(mDef, "`n[",false, s+1))						;end index
		e := StrLen(mDef)		

 	if *(&mDef+s-1) = 10											;skip `n if on start
		s++
	s += Strlen(mnu)+3, this := SubStr(mDef, s, e-s+1)				;extract menu def

	menus .= mnu "`n"
	Loop, parse, this, %sep%, `n`r
	{
		s := A_LoopField
		IfEqual, s, ,continue
		IfEqual, s,-,SetEnv,s,										;separator
		if j := RegExMatch(s, "S)(?<=\<).+?(?=\>)", out)			;check for submenu	
			 s := SubStr(s, 1, InStr(s,"=")-1),   ShowMenu( mDef, out, sub, sep, 1)
		else if k := InStr(s,"=")									;if it has = after it remove it
			s := SubStr(s, 1, k-1)

		if (c:=(*&s = 43)) or ((*&s=42) and c:=2)
			StringTrimLeft, s, s, 1
		Menu, %mnu%, Add, %s%, % j ? ":" out : p
		IfEqual, c, 1, Menu, %mnu%, Check, %s%
		IfEqual, c, 2, Menu, %mnu%, Disable, %s%

	}

	IfEqual, r, 0 , Menu, %mnu%, Show								;if not in recursion, show
	return menus
}
;------------------------------------------------------------------------------------------------
; Function:		ShowMenu_Data
;				Get data associated with menu item
;  
; Parameters: 
;				mDef	- Textual menu definition.
;				item	- Menu item which associated data will be returned, if omited defaults to A_ThisMenuItem
;				
; Returns:      
;				Associated data or empty string if no data is associated with item.
ShowMenu_Data(mDef, item="") {
	if item=
		item := A_ThisMenuItem
	mDef .= "`n"
	j := InStr(mDef, item "=")
	IfEqual, j, 0, return 
	j += StrLen(item)+1
	return SubStr(mDef, j, InStr(mDef, "`n", false, j)-j)
}